Streaming video with Raspberry Pi

這次的實作是在 Raspberry Pi 上使用 Camera module,並使用 raspivid 以及 ffmpeg 實現 Video streaming server,並在手機上看到 Camera 的影像。

Requirements

  • Raspberry Pi Model B Gen.2
  • Raspberry Pi Camera Module
  • 一顆熱情的心

Equipment setup (hardware)

當取得 Raspberry Pi & Camera 後,我們首先將其組裝起來,在組裝 Camera 之前請先消除身上的靜電,以免損壞了 Camera (畢竟一個也不便宜呢!)。
硬體組裝的步驟大致為:

  1. 找到 Camera 的插槽,這個插槽位於 HDMI 以及音效孔之間,輕輕地向上拉開。
  2. 將 Camera 模組的排線插入插槽中,排線尾端的金屬接頭朝向 HDMI 孔的方向。
  3. 將插栓向下推 (基本上無論怎麼推,排線尾端的金屬接頭都會外露)

在組裝完成後,我們來設定軟體的部分吧。

1
2
3
sudo apt-get update
sudo apt-get dist-upgrade
sudo raspi-config

alt raspi-config
請選擇 Enable Camera 進入下一頁後選擇 Enable,然後重新啟動 Raspiberry Pi。

Raspberry Pi Camera 的使用

既然我們都接好 Camera 了,那為何不先玩一下呢?
Raspberry Pi 很善良的地先提供了二組命令讓我們使用 raspistill 以及 raspivid

raspistill

首先我們來看 raspistill,在 terminal 中直接鍵入 raspistill 不加任何參加後可以直接得到該命令的 help message,從 help message 的說明可以得知是用來在一段時間內產生一個 still file。說白了,就是讓你可以從 Camera 上拿到一張圖啦!

以下示範取得一張 JPEG file

1
raspistill -o image.jpg

-o 代表輸出的資料要存放的地方,如果給定的是一個檔名的話,則會存成該檔案。
以下取得一張 320 x 240 的 JPEG file

1
raspistill -w 320 -h 240 -o image.jpg

取得一張上下顛倒 (vertical flip) 及影像 (mirror) 的 JPEG file (通常是因為你的 Camera module 會躺在桌上,看到的圖都是顛倒的)

1
raspistill -vf -hf -o image.jpg

在一分鐘內,每隔一秒抓一張圖 (*拿到這些圖後,可以做成縮時錄影)

1
raspistill -t 60*1000 -tl 1*1000 -o image%02d.jpg

對縮時錄影有興趣的話可以參考這篇文章

也可以自己寫一隻小程式,透過 pipe 將 stdin 的 data 讀取進來。

1
raspistill -vf -o - | my_program

剛才提到 -o 為資料輸出的地方,如果要輸出至 stdout 可以寫成 -o -

接著使用 raspistill 輸出 M-JPEG 吧。

1
2
3
sudo apt-get install cmake libjpeg62-dev
git clone https://github.com/jacksonliam/mjpg-streamer.git
cd mjpg-streamer/mjpg-streamer-experimental/

接下來我們要修改一些 Makefile,請使用任一套你能使用的文字編輯器打開 Makefile,然後找到下面這一行,並把前面的 “#” 移除並存檔。

1
2
3
...
# PLUGINS += input_file.so
...

修改完後,我們進行編譯動作make clean all

前面做了這麼多,也就表示我們將會使用 mjpg-streamer 這個程式來協助我們完成 MJPEG streamer 的動作,在成功安裝好 mjpg-streamer 之後,可以先試一下效果:

1
LD_LIBRARY_PATH=./ ./mjpg_streamer -i "input_raspicam.so" -o "output_http.so"

現在開啟 VLC 並輸入網址 http://{the_ip}:8080/?action=stream,哇!可以看到影像了。

不過這一節談的是raspistill,當然是無論如何也要牽扯一下啦。

1
2
raspistill -bm -n -vf -hf -w 640 -h 480 -q 50 -o frame.jpg -t 0 -tl 200 &
LD_LIBRARY_PATH=./ ./mjpg_streamer -i "input_file.so -f . -n frame.jpg" -o "output_http.so -w ./www"

在 raspistill 中,我們開啟了 -bm 暴力抓圖模式,以及 -t 0 -tl 200 -o frame.jpg 每隔 0.2 秒刷新 frame.jpg 這張圖。
在 mjpg_streamer 中可以透過 input_file 這個 plug-in 將 frame.jpg 讀進來產生動態圖的效果,我們在 -o 參數中加入了 -w 來指定 http folder。

接著在瀏覽器上輸入 http://%IP%:8080/
alt snapshot

raspivid

相同的,help message 告訴我們這組命令會讓我們從 camera module 上得到一段 h.264 格式的 video。

我們馬上來抓一段視頻。

1
raspivid -o video.h264

透過上述的命令,我們可以得到一段預設為五秒的 h.264 video,最後這段影片可以直接透過 VLC 播放。

一種簡單的作法是透過 scp 把 video.h264 拷貝回自己的電腦上播放 scp pi@IP:/YOUR_FOLDER/video.h264 ./

讓我們來錄一段 1280x720, bitrate = 512000, fps = 25 長度 30 秒的影片:

1
raspivid -w 1280 -h 720 -fps 25 -b 512000 -t 30000 -o video.h264

也可以透過 VLC 產生 RTSP stream:

1
2
raspivid -t 0 -w 640 -h 480 -fps 10 -o - | cvlc -vvv stream:///dev/stdin \\
--sout '#rtp{sdp=rtsp://:8554/}' :demux=h264

透過 raspivid 取得 video data,並輸出至 stdout,然後使用 cvlc (a VLC console program) 來轉換成 RTSP stream,-vvv 指的是印出 verbose 訊息 (-v or -vv or -vvv),stream: 參數表示其串流影像來源,在此例上是 stdin;--sout 參數後面表示將會把影像串流輸出成 RTSP 格式。
這時候你可以透過手機或電腦上的 RTSP player 來連線至 rtsp://[the ip]:8554/ 來播放囉。